#pragma once
#include <iostream>
#include "mySock.hpp"
#include "pthread.h"
#include <functional>
#include "myProtocol.hpp"
using namespace std;
const static uint16_t default_port = 8080;
using func_t = function<Response(const Request &)>;

class tcpServer;

class ThreadData
{
public:
    ThreadData(const int &sock, const string &ip, const uint16_t &port, tcpServer *tcp)
        : sock_(sock), ip_(ip), port_(port), tcp_(tcp)
    {
    }

    ~ThreadData()
    {
    }

public:
    int sock_;
    string ip_;
    uint16_t port_;
    tcpServer *tcp_;
};

class tcpServer
{
public:
    tcpServer(uint16_t port, func_t func)
        : _port(port), _func(func)

    {
    }

    tcpServer()
    {
    }
    ~tcpServer()
    {
    }
    void Init()
    {
        _listenSock.Socket();
        _listenSock.Bind(_port);
        _listenSock.Listen();
        logMessge(INFO, "准备就绪！");
    }
    void Start()
    {
        string cilentIp;
        uint16_t cilentPort;
        while (1)
        {

            int sock = _listenSock.Accept(&cilentIp, &cilentPort);
            if (sock < 0)
            {
                continue;
            }
            pthread_t tid;
            ThreadData *td = new ThreadData(sock, cilentIp, cilentPort, this);
            pthread_create(&tid, nullptr, threadRoutine, td);
        }
    }
    void serverIo(int sock, string cilentIp, uint16_t cilentPort)
    {
        string inbuffer;
        while (1)
        {
            string str;
            int n = ReadPackage(sock, inbuffer, &str);
            if (n == -1)
            {
                logMessge(FATAL,"没读到任何报文");
                break;
            }
            else if (n == 0)
            {
                logMessge(WARING,"没读到完整的报文");
                continue;
            }
            else
            {

                RemoveHeader(str);
                Request rq;
                rq.DeSerialize(str); // 反序列化
                Response rsp = _func(rq);
                string _rsp_str;
                rsp.Serialize(_rsp_str);
                AddHeader(_rsp_str);
                send(sock, _rsp_str.c_str(), _rsp_str.size(), 0);
            }
        }
        close(sock);
    }
    static void *threadRoutine(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);
        td->tcp_->serverIo(td->sock_, td->ip_, td->port_);
        delete td;
        return nullptr;
    }

private:
    Sock _listenSock;
    uint16_t _port;
    func_t _func;
};